#include "cpu.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <stdlib.h>
#include <cstring>
#include <string>
using namespace std;

//
CPU::CPU()
{
    cpuStat = "/proc/stat";
    cpuLoadavg = "/proc/loadavg";
    index = 0;
    // 初始化stat数组
    for(int i = 0; i < 2; i++){
        for(int j = 0; j < 8; j++){
            stat[i][j] = "0";
        }
    }
}

CPU::~CPU()
{
}

/*
Example:    0.16 0.27 0.22 2/238 4440
*/
void CPU::GetCPUFromLoadavg(CpuLoadavg *pLoadavg)
{
    char loadavgBuf[1024];  //存放loadavg文件内容
    char *itemValue = NULL;     //存放每一项的数值
    char delims[] = " ";    //分割符

    FILE *fp = fopen(cpuLoadavg,"r");
    if(fp == NULL){
        ErrorLog *pErr = new ErrorLog();
        pErr->log_error(AT,"无法打开文件：/proc/loadavg");
        exit(1);
    }
    else{
         fgets(loadavgBuf,1024,fp);

         itemValue = strtok(loadavgBuf,delims);
         pLoadavg->mins1 = itemValue;
        //
         itemValue = strtok(NULL,delims);
         pLoadavg->mins5 = itemValue;
         //
         itemValue = strtok(NULL,delims);
         pLoadavg->mins15 = itemValue;

    }
}

/*
获取stat文件第一行的内容，并计算出当前CPU使用率
*/
void CPU::GetCPUFromStat(CpuStatusTime *pStatusTime)
{
    double vDeta[4];   //存放不同时刻CPU在各个状态运行的时间差
    double pUse;

    ifstream statStream(cpuStat);

    if(!statStream){
        ErrorLog *pErr = new ErrorLog();
        pErr->log_error(AT,"无法打开文件：/proc/stat");
        exit(1);
    }else{
        statStream >> stat[index][0] >> stat[index][1] >> stat[index][2]
                >> stat[index][3] >> stat[index][4] >> stat[index][5]
                >> stat[index][6] >> stat[index][7];

        pStatusTime->user    =  QString::fromStdString(stat[index][1]);
        pStatusTime->nice    =  QString::fromStdString(stat[index][2]);
        pStatusTime->sys     =  QString::fromStdString(stat[index][3]);
        pStatusTime->idle    =  QString::fromStdString(stat[index][4]);
        pStatusTime->ioWait  =  QString::fromStdString(stat[index][5]);
        pStatusTime->irq     =  QString::fromStdString(stat[index][6]);
        pStatusTime->softIrq =  QString::fromStdString(stat[index][7]);

        int oldIndex = (index + 1) % 2;

        vDeta[0] = atof(stat[index][1].c_str()) - atof(stat[oldIndex][1].c_str());
        vDeta[1] = atof(stat[index][2].c_str()) - atof(stat[oldIndex][2].c_str());
        vDeta[2] = atof(stat[index][3].c_str()) - atof(stat[oldIndex][3].c_str());
        vDeta[3] = atof(stat[index][4].c_str()) - atof(stat[oldIndex][4].c_str());

        double total = vDeta[0] + vDeta[1] + vDeta[2] + vDeta[3];

        // 计算CPU使用率
        if(total){  //表示不在同一时刻
            pUse = (total - vDeta[3]) / total;
            pStatusTime->currentUsage = QString("%1").arg(pUse);
            index = (index + 1) % 2;
        }
    }
}

// 分解获取的vmstat文件内容
void CPU::SeperateString(char *result, CpuItemFromCommand *pItemFromCommand)
{
    char *tmp = NULL;
//    char delim[] = "\n";
    char delims[] = " ";
//    char tmpcpy[200];

//    tmp = strtok(result,delim);
//
//    tmp = strtok(NULL,delim);
//
//    tmp = strtok(NULL,delim); // 在这个地方为什么将后面的取值截断了呢？
////    printf("%s\n",tmp);
//    // 此时的tmp 为“      5  0      0 877560  92288 557300    0    0    70    57  307  943 13  4 81  2”
//    // tmp此时怎么回事“    4  0  14968 104636 563108 428008    0    ”
//
//
//    strcpy(tmpcpy,tmp);
    // running processes
    tmp = strtok(result, delims);
//    tmp = strtok(tmpcpy,delims);
    pItemFromCommand->running = tmp;
    // blocked
    tmp = strtok(NULL,delims);
    pItemFromCommand->blocked = tmp;

    for(int i = 0; i < 8 ; i++ )
        tmp =strtok(NULL,delims);
    // interrupt per second
//    printf("%s\n", tmpcpy);
    tmp =strtok(NULL,delims);
    pItemFromCommand->intr = tmp;
    // context
    tmp = strtok(NULL,delims);
    pItemFromCommand->ctxt = tmp;

}

// 执行vmstat命令，并通过字符串分解，获取数值
void CPU::GetCPUFromCommand(CpuItemFromCommand *pItemFromCommand)
{

    const char *fileName = "cpu.out";
    const char *command = "vmstat";
    int size = 1024;
    char result[size];

    ExecuteCommand(command, fileName, result, size, 3);
//    CommandPipe(command,result,size);
    // 没有获得数值
    printf("%s\n", result);
    SeperateString(result,pItemFromCommand);
}

void CPU::GetCPUInfo(CPU *pCPU, QMultiMap<QString, QPair<QString, QString> > *pmultiMap)
{
    QPair<QString, QString> kv;
    QString cate = "CPU";

    GetCPUFromStat(&(pCPU->sStatus));
    // 需要将结构体内容送入map中
    kv.first = "user";
    kv.second = pCPU->sStatus.user;
    pmultiMap->insert(cate,kv);
    //
    kv.first = "nice";
    kv.second = pCPU->sStatus.nice;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "sys";
    kv.second = pCPU->sStatus.sys;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "idle";
    kv.second = pCPU->sStatus.idle;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "ioWait";
    kv.second = pCPU->sStatus.ioWait;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "irq";
    kv.second = pCPU->sStatus.irq;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "softIrq";
    kv.second = pCPU->sStatus.softIrq;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "currentUsage";
    kv.second = pCPU->sStatus.currentUsage;
    pmultiMap->insert(cate, kv);

    // 果然问题出在管道这个地方
    GetCPUFromCommand(&(pCPU->sItems));
    kv.first = "intr";
    kv.second = pCPU->sItems.intr;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "ctxt";
    kv.second = pCPU->sItems.ctxt;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "running";
    kv.second = pCPU->sItems.running;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "blocked";
    kv.second = pCPU->sItems.blocked;
    pmultiMap->insert(cate, kv);

    GetCPUFromLoadavg(&(pCPU->sLoad));
    kv.first = "mins1";
    kv.second = pCPU->sLoad.mins1;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "mins5";
    kv.second = pCPU->sLoad.mins5;
    pmultiMap->insert(cate, kv);
    //
    kv.first = "mins15";
    kv.second = pCPU->sLoad.mins15;
    pmultiMap->insert(cate, kv);
}
